import ast
from typing import List, Dict

import pathway as pw


class EsSectionProcessPipeline:
    """
    国自然基金信息段落处理管道，用于 ETL transform 阶段。

    功能
    ----
    - 对每条信息记录的段落进行源文本解析和拼接，生成全文字符串；
    - 对 apply_info 字段进行默认值填充；
    - 添加默认地区信息；
    - 对 media_info 字段解析为字典对象。

    Attributes
    ----------
    area_filter_default : dict
        默认地区信息，当源数据缺失时使用。
    apply_code_default : dict
        默认学部/领域信息，当源数据缺失时使用。
    """

    area_filter_default = {
        "area_id": "0",
        "area_name": "全国"
    }

    apply_code_default = {
        "apply_code": "*",
        "code_name": "其他"
    }

    def apply(self, value):
        """
        对 Pathway 表对象应用段落处理逻辑。

        Parameters
        ----------
        value : pw.Table
            Pathway 表对象，包含 sections 和 apply_info 等字段。

        Returns
        -------
        pw.Table
            处理完成后的 Pathway 表对象，增加 sections_text、apply_info 和 area_info。
        """
        value = value.with_columns(
            sections=pw.apply(
                self.get_src_text,
                value.sections
            )
        )
        value = value.with_columns(
            sections_text=pw.apply(
                self.get_sections_text,
                value.sections
            )
        )
        value = value.with_columns(
            apply_info=pw.apply(
                self.get_apply_info,
                value.apply_info
            )
        )
        value = value.with_columns(
            area_info=self.area_filter_default
        )

        # _id
        return value

    def get_apply_info(self, apply_info):
        """
        填充默认学部/领域信息。

        Parameters
        ----------
        apply_info : dict or None
            原始 apply_info 字段内容。

        Returns
        -------
        dict
            若原始字段为空，返回默认值；否则返回原始值。
        """
        if not apply_info:
            return self.apply_code_default
        return apply_info

    def get_sections_text(self, sections):
        """
        将段落列表拼接为全文字符串，提取 src_text 中的 text 字段。

        Parameters
        ----------
        sections : list
            段落对象列表，通常包含 src_text 结构。

        Returns
        -------
        str
            拼接后的段落文本，每个段落间以换行符分隔。
        """
        es_text_parts = []
        if not sections:
            return ""
        for item in sections:
            item = item.as_dict()
            src_text = item.get("src_text", {})
            if not src_text:
                continue
            # src_text 预期包含 children 节点，逐个拼接 text 字段
            children = src_text.get("children", [])
            temp_parts = []
            for child in children:
                try:
                    text_val = child.get("text") if isinstance(child, dict) else None
                    if text_val:
                        temp_parts.append(text_val)
                except Exception:
                    # 忽略单个子项解析错误，继续处理其它子项
                    continue

            if temp_parts:
                es_text_parts.append("".join(temp_parts))
        return "\n".join(es_text_parts)

    def get_src_text(self, sections) -> List[Dict]:
        """
        标准化段落列表，解析 media_info 并确保 src_text、dst_text 字段存在。

        Parameters
        ----------
        sections : list
            原始段落对象列表。

        Returns
        -------
        List[Dict]
            处理后的段落字典列表，每个字典包含 src_text、dst_text、media_info。
        """
        sections_list = []
        if not sections:
            return []
        for item in sections:
            item = item.as_dict()
            # 确保 src_text、dst_text 字段存在
            if not item.get("src_text"):
                item['src_text'] = {}
            if not item.get("dst_text"):
                item['dst_text'] = {}
            # 解析 media_info 为字典
            if item.get("media_info"):
                item['media_info'] = ast.literal_eval(item['media_info'])
            else:
                item['media_info'] = {}

            sections_list.append(item)
        return sections_list
